<?php
/**
 * @package account
 */
class AccountAdjustment extends DataExtension {
    public static function get_extra_config($class, $extension, $args) {
        return array(
            'db' => array(
                'Amount' => 'Currency',
                'Remark' => 'Varchar(250)'
            ),
            'has_one' => array(
                'Member' => 'Member',
                'Admin' => 'Member',
                'Account' => Config::inst()->get($extension, $class)
            ),
            'searchable_fields' => array(
            	'Created' => array(
					'field' => 'DateField',
					'filter' => 'DateMatchFilter'
				),
                'Member.Username',
                'Member.FirstName',
                'Member.Surname',
                'Amount' => array(
		            'filter' => 'GreaterThanOrEqualFilter'
		        ),
                'Remark',
                'Admin.Username'
            ),
            'summary_fields' => array(
            	'Created.Nice',
                'Member.Username',
                'Member.Name',
                'Amount',
                'Remark',
                'Admin.Username'
            ),
            'defaults' => array('Remark' => 'Adjust by admin'),
            'default_sort' => 'Created DESC, ID DESC',
            'create_table_options' => array('MySQLDatabase' => 'ENGINE=InnoDB')
        );
    }

    function augmentWrite(&$manipulation) {
        $tables = array_keys($manipulation);
        $version_table = array();
        foreach($tables as $table) {
            $baseDataClass = ClassInfo::baseDataClass($table);

            $isRootClass = ($table == $baseDataClass);

            if($isRootClass) {
                if($manipulation[$table]['command'] == 'insert' || $manipulation[$table]['command'] == 'update') {
                    $manipulation[$table]['fields']['AdminID'] = isset($manipulation[$table]['fields']['AdminID']) && $manipulation[$table]['fields']['AdminID'] ? $manipulation[$table]['fields']['AdminID'] : Member::currentUserID();
                }
            }
        }
    }
	
	function updateFieldLabels(&$labels) {
		$labels['Created'] = _t('AccountAdjustment.ADJUST_ON', 'Adjust On');
		$labels['Created.Nice'] = _t('AccountAdjustment.ADJUST_ON', 'Adjust On');
		$labels['Amount'] = _t('AccountAdjustment.AMOUNT', 'Amount');
		$labels['Remark'] = _t('AccountAdjustment.REMARK', 'Remark');
		$labels['Admin.Username'] = _t('AccountAdjustment.ADJUSTED_BY', 'Adjusted By');
		$labels['AdminID'] = _t('AccountAdjustment.ADJUSTED_BY', 'Adjusted By');
		$labels['Admin'] = _t('AccountAdjustment.ADJUSTED_BY', 'Adjusted By');
        $labels['Member.Username'] = _t('AccountAdjustment.USERNAME', 'Username');
		$labels['Member.Name'] = _t('AccountAdjustment.NAME', 'Name');
		$labels['Member'] = _t('AccountAdjustment.NAME', 'Name');
		$labels['Member.FirstName'] = _t('AccountAdjustment.FIRSTNAME', 'First Name');
		$labels['Member.Surname'] = _t('AccountAdjustment.SURNAME', 'Surname');
    }

    function updateCMSFields(FieldList $fields) {
        if($this->owner->exists()) {
            $fields->removeByName('AccountID');
            $fields->makeFieldReadonly('AdminID');
            $fields->makeFieldReadonly('Amount');
            $fields->makeFieldReadonly('Remark');
            $fields->makeFieldReadonly('MemberID');
        } else {
            $fields->insertBefore(UsernameField::create('SetUsername', _t('AccountAdjustment.USERNAME', 'Username')), 'Amount');
            $fields->push(HiddenField::create('AccountClass', 'AccountClass', Config::inst()->get($this->class, $this->owner->class)));
            $fields->removeByName('AccountID');
            $fields->removeByName('AdminID');
            $fields->removeByName('MemberID');
        }
    }

	function validate(ValidationResult $validationResult) {
		if($this->owner->SetUsername && !$this->owner->MemberID){
			$this->owner->MemberID = Distributor::get_id_by_username($this->owner->SetUsername);
		}
		
		if(!$this->owner->MemberID) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('AccountAdjustment.INVALID_MEMBER_ID', 'Invalid member id'), 'INVALID_MEMBER_ID');
            $validationResult->combineAnd($subvalid);
        }
        
        if(!$this->owner->ID && $this->owner->Amount == 0){
			$subvalid = new ValidationResult();
            $subvalid->error(_t('AccountAdjustment.AMOUNT_CANNOT_ZERO', 'Amount cannot zero'), "AMOUNT_CANNOT_ZERO");
            $validationResult->combineAnd($subvalid);
		} else {
	        if(!$this->owner->ID && $this->owner->Amount < 0) {
	        	$account_class = $this->getAccountClass();
	            $balance = Account::get($account_class, $this->owner->MemberID)->Balance;
	            if(abs($this->owner->Amount) > $balance){
	                $subvalid = new ValidationResult();
	                $subvalid->error(_t('AccountAdjustment.INSUFFICIENT_BALANCE', 'Insufficient account balance ({balance})', 'Display insufficient account balance', array('balance' => Account::get($account_class, $this->owner->MemberID)->obj('Balance')->Nice())), "INSUFFICIENT_ACCOUNT_BALANCE");
	                $validationResult->combineAnd($subvalid);
	            }
	        }
		}

        return $validationResult;
    }

    function getCMSValidator() {
        return AccountAdjustment_Validator::create();
    }

    function onBeforeWrite() {
        if($this->owner->MemberID == '' && $this->owner->SetUsername != '') {
            $this->owner->MemberID = Distributor::get_id_by_username($this->owner->SetUsername);
        }

        if(!$this->owner->AccountID && $this->owner->MemberID && $this->owner->Amount != 0) {
        	$account_class = $this->getAccountClass();
            $data = array(
                'Type' => 'Adjustment',
                'Description' => $this->owner->Remark
            );

            if($this->owner->Amount > 0) {
                $data['Credit'] = $this->owner->Amount;
            } else {
                $data['Debit'] = abs($this->owner->Amount);
            }

            $this->owner->AccountID = $account_class::create_statement($data, $this->owner->MemberID);
        }
    }

    function ViewHTML() {

    }

    function ViewPDF() {

    }

    function ViewPrint() {

    }

	function getAccountClass(){
		return Config::inst()->get($this->class, $this->owner->class);
	}
}

class AccountAdjustment_Validator extends RequiredFields {

    protected $customRequired = array(
        'SetUsername',
        'Amount',
        'Remark'
    );

    /**
     * Constructor
     */
    public function __construct() {
        $required = func_get_args();
        if(isset($required[0]) && is_array($required[0])) {
            $required = $required[0];
        }
        $required = array_merge($required, $this->customRequired);

        parent::__construct($required);
    }

    /**
     * Check if the submitted member data is valid (server-side)
     *
     * Check if a member with that email doesn't already exist, or if it does
     * that it is this member.
     *
     * @param array $data Submitted data
     * @return bool Returns TRUE if the submitted data is valid, otherwise
     *              FALSE.
     */
    function php($data) {
        $valid = parent::php($data);

        $amount = isset($data['Amount']) ? $data['Amount'] : 0;
        $memberid = isset($data['SetUsername']) ? Distributor::get_id_by_username($data['SetUsername']) : 0;
        $account_class = isset($data['AccountClass']) ? $data['AccountClass'] : '';

        // if we are in a complex table field popup, use ctf[childID], else use
        // ID
        if(isset($_REQUEST['ctf']['childID'])) {
            $id = $_REQUEST['ctf']['childID'];
        } elseif(isset($_REQUEST['ID'])) {
            $id = $_REQUEST['ID'];
        } else {
            $id = null;
        }

        if($amount == 0) {
            $this->validationError('Amount', _t('AccountAdjustment.AMOUNT_CANNOT_ZERO', 'Amount cannot zero'), 'required');
            $valid = false;
        } else if($amount < 0 && $memberid) {
            $balance = Account::get($account_class, $memberid)->Balance;
            if(abs($amount) > $balance) {
                $this->validationError('Amount', _t('AccountAdjustment.INSUFFICIENT_BALANCE', 'Insufficient account balance ({balance})', 'Display insufficient account balance', array('balance' => Account::get($account_class, $memberid)->obj('Balance')->Nice())), 'required');
            }
            $valid = false;
        }

        return $valid;
    }

}
?>
